package com.demo.jwt.interceptors;

import com.demo.jwt.annotation.UserLogin;
import com.demo.jwt.exception.MyException;
import com.demo.jwt.exception.RespStatus;
import com.demo.jwt.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //放行options请求类型
        if(HttpMethod.OPTIONS.toString().equals(request.getMethod().toString())){
            return true;
        }

        //判断是否需要登陆
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            UserLogin userLogin = handlerMethod.getMethodAnnotation(UserLogin.class);
            if (userLogin == null) {
                //没有@UserLogin注解放行通过
                return true;
            }else{
                //有@UserLogin注解,需要验证是否登陆，即验证token是否有效
                // 获取请求头信息authorization信息
                String authorization = request.getHeader(JwtUtil.AUTH_HEADER_KEY);
                //获取 token 参数令牌
                String tokenParam = request.getParameter(JwtUtil.TOKEN_KEY);
                //判断token令牌的携带方式
                if(!StringUtils.isEmpty(authorization) && authorization.startsWith(JwtUtil.TOKEN_PREFIX)){
                    //1、请求头 header 携带 token 令牌
                    //去除 header 令牌中的 "Bearer "字符串
                    String token = authorization.substring(7);
                    //检验token是否有效
                    Map<String,Object> map = new HashMap<>();
                    try {
                        JwtUtil.checkToken(token);
                    }catch (Exception e){
                        log.info(RespStatus.TOKEN_ERROR.getMessge(),e.getMessage());
                        throw new MyException(RespStatus.TOKEN_ERROR);
                    }

                }else if(StringUtils.isEmpty(authorization) && !StringUtils.isEmpty(tokenParam)){
                    //2、使用参数 token 携带令牌方式
                    //检验token是否有效
                    Map<String,Object> map = new HashMap<>();
                    try {
                        JwtUtil.checkToken(tokenParam);
                    }catch (Exception e){
                        log.info(RespStatus.TOKEN_ERROR.getMessge(),e.getMessage());
                        throw new MyException(RespStatus.TOKEN_ERROR);
                    }
                }else if(!StringUtils.isEmpty(authorization) && !StringUtils.isEmpty(tokenParam)){
                    //3、两种携带 token 令牌的方式都存在,默认获取 header 中的令牌
                    //检验token是否有效
                    Map<String,Object> map = new HashMap<>();
                    try {
                        JwtUtil.checkToken(authorization.substring(7));
                    }catch (Exception e){
                        log.info(RespStatus.TOKEN_ERROR.getMessge(),e.getMessage());
                        throw new MyException(RespStatus.TOKEN_ERROR);
                    }
                }else{
                    //4、获取不到 token 令牌 抛出未登录异常
                    log.info(RespStatus.NO_LOGIN.getMessge());
                    throw new MyException(RespStatus.NO_LOGIN);
                }
            }
        }

        return true;
    }
}
